//策略模式

//实例1
#include<iostream>
#include<string>
#include<memory>
using namespace std;

//高层策略接口
class Strategy
{
public:
	virtual double CalcPrice(double goodsPrice)
	{
		return 0;
	}
};


//具体策略
//普通用户策略
class NormalCustomerStrategy :public Strategy
{
public:
	double CalcPrice(double goodsPrice) override
	{
		//普通用户没有折扣
		cout << "普通用户没有折扣。" << endl;
		return goodsPrice;
	}
};


//老客户策略
class OldCustomerStrategy : public Strategy
{
public:
	double CalcPrice(double goodsPrice) override
	{
		//老客户，95折
		cout << "老客户，95折。" << endl;
		return goodsPrice * (1 - 0.05);
	}
};


//大客户策略
class LargeCustomerStrategy : public Strategy
{
	double CalcPrice(double goodsPrice) override
	{
		//大客户，9折
		cout << "大客户，9折。" << endl;
		return goodsPrice * 0.9;
	}
};

//策略上下文
class Price
{
private:
	unique_ptr<Strategy> pStrategy = nullptr;
public:
	Price(Strategy* strategy) : pStrategy(strategy) {}

	double Quote(double goodsPrice)
	{
		if (pStrategy != nullptr)
			return pStrategy->CalcPrice(goodsPrice);
		return 0;
	}
};


int main()
{
	{
		Price price(new NormalCustomerStrategy);
		double goodsPrice = price.Quote(100);
		cout << "普通客户最终价: " << goodsPrice << endl;
	}

	{
		Price price(new OldCustomerStrategy);
		double goodsPrice = price.Quote(100);
		cout << "老客户最终价: " << goodsPrice << endl;
	}

	{
		Price price(new LargeCustomerStrategy);
		double goodsPrice = price.Quote(100);
		cout << "大客户最终价: " << goodsPrice << endl;
	}

	return 0;
}

/*
普通用户没有折扣。
普通客户最终价: 100
老客户，95折。
老客户最终价: 95
大客户，9折。
大客户最终价: 90
*/










//实例2
#include<algorithm>
#include<iostream>
#include<memory>
#include<string>
#include<vector>
using namespace std;

class strategy			//抽象策略接口
{
public:
	virtual ~strategy() {};
	virtual string doAlgorithm(const vector<string>& v) = 0;
};

class context
{
private:
	shared_ptr<strategy> mStrategy;
public:
	context(shared_ptr<strategy> strategy):mStrategy(strategy) {}
	~context() {}

	void setStrategy(shared_ptr<strategy> strategy)
	{
		mStrategy.reset();
		this->mStrategy = strategy;
	}

	void doSomeBusinessLogic() const
	{
		cout << mStrategy.get()->doAlgorithm({ "x", "c", "d", "z", "l", "a"}) << endl;
	}
};


class concreteStrategyA : public strategy
{
public:
	string doAlgorithm(const vector<string>& v) override
	{
		string res = "";
		for_each(v.begin(), v.end(), [&res](const string& s){ res += s; });
		return res;
	}
};


class concreteStrategyB :public strategy
{
public:
	string doAlgorithm(const vector<string>& v) override
	{
		string res = "";
		for_each(v.begin(), v.end(), [&res](const string& s) { res += s; });
		sort(res.begin(), res.end());
		return res;
	}
};


void clientCode()
{
	shared_ptr<strategy> strategyA = make_shared<concreteStrategyA>();
	shared_ptr<strategy> strategyB = make_shared<concreteStrategyB>();

	shared_ptr<context> contextA = make_shared<context>(strategyA);
	shared_ptr<context> contextB = make_shared<context>(strategyB);
	contextA.get()->doSomeBusinessLogic();
	contextB.get()->doSomeBusinessLogic();

}

int main()
{
	clientCode();
	return 0;
}


/*
xcdzla
acdlxz
*/
